#include "chunk_file_loger.hpp"
#include <libgen.h>
#include <string.h>

namespace lxz
{
    chunk_file_loger::chunk_file_loger()
        : path_(""), filename_(""), bytes_per_file_(1 << 20)
    {
    }
    chunk_file_loger::~chunk_file_loger()
    {
    }

    int32_t chunk_file_loger::init(log_level level, const char *file)
    {
        char *str_dup = nullptr;

        level_ = level;

        str_dup = strdup(file);
        path_ = dirname(str_dup);
        free(str_dup);

        looping_ = true;
        thread_ = std::make_shared<std::thread>(&chunk_file_loger::flush, this);

        return 0;
    }

    void chunk_file_loger::flush(void)
    {
        while (looping_)
        {
            if (!fp_)
            {
                GenerateFilename();

                fp_ = fopen(filename_.c_str(), "w");
                if (!fp_)
                {
                    abort();
                }
            }

            if (ftell(fp_) >= (long)bytes_per_file_)
            {
                fclose(fp_);
                fp_ = nullptr;

                GenerateFilename();

                fp_ = fopen(filename_.c_str(), "w");
                if (!fp_)
                {
                    abort();
                }
            }

            {
                std::unique_lock<std::mutex> lock(mutex_);

                cond_var_.wait(lock, [this](void) -> bool
                               { return this->enable_flush_ == true; });

                enable_flush_ = false;

                if (out_queue_.empty() && !(in_queue_.empty()))
                {
                    out_queue_.swap(in_queue_);
                }
            }

            while (!(out_queue_.empty()))
            {
                fputs(out_queue_.front().c_str(), fp_);
                fflush(fp_);

                out_queue_.pop();
            }
        }
    }

    void chunk_file_loger::GenerateFilename(void)
    {
        time_t time_tp = 0;
        struct tm time_st = {0};
        char time_fmt[128] = {0};
        char filenamebuf[1024] = {0};

        time_tp = time(nullptr);

        if (localtime_r(&time_tp, &time_st) == nullptr)
        {
            return;
        }

        (void)strftime(time_fmt, sizeof(time_fmt), "%Y-%m-%d-%H-%M-%S", &time_st);

        if (snprintf(filenamebuf, 1024, "%s/%s.log", path_.c_str(), time_fmt) < 0)
        {
            return;
        }

        filename_ = filenamebuf;
    }
}